package com.hontech.pastacooking.conn

import com.hontech.pastacooking.app.bus
import com.hontech.pastacooking.event.CookProgEvent
import com.hontech.pastacooking.event.FridgeStatusEvent
import com.hontech.pastacooking.event.MainExceptEvent
import com.hontech.pastacooking.event.ScanBarcodeEvent
import com.hontech.pastacooking.ext.MainStatusEvent
import com.hontech.pastacooking.ext.isSetBit
import com.hontech.pastacooking.model.FridgeStatus
import com.hontech.pastacooking.model.MainStatus
import com.hontech.pastacooking.net.NetClient
import com.hontech.pastacooking.net.REQ_FRIDGE_STATUS
import com.hontech.pastacooking.net.REQ_MAIN_STATUS
import com.hontech.pastacooking.serial.ByteView
import com.hontech.pastacooking.serial.UInt8
import com.hontech.pastacooking.utils.S

object MainProto {

    const val Except = 0x01
    const val OtaStart = 0x02
    const val OtaTranslate = 0x03
    const val OtaComplete = 0x04
    const val FridgeStatusUpload = 0x05
    const val StatusUpload = 0x06
    const val TestCargoRoate = 0x07
    const val TestCargoElevator = 0x08
    const val TestCargoFetch = 0x09
    const val TestHeatDoor = 0x0A
    const val TestExternPush = 0x0B
    const val TestPastaDoor = 0x0C
    const val TestPickDoor = 0x0D
    const val TestPick = 0x0E
    const val TestScanner = 0x0F
    const val Scan = 0x10
    const val SetCleanParam = 0x11
    const val QueryCleanParam = 0x12
    const val PickupCooking = 0x13
    const val DeviceReset = 0x14
    const val TestLed = 0x15
    const val PreProc = 0x16
    const val RKCRead = 0x17
    const val RKCWrite = 0x18
    const val Keepalive = 0x19
    const val BUSYCtrl = 0x1A
    const val TestCooking = 0x1B


    var status = MainStatus()
        private set

    var fridge = FridgeStatus()
        private set

    private fun progMsg(step: Int, ec: Int): String {
        return "${prog(step)}:${errMsg(ec)}"
    }

    private fun prog(step: Int): String {
        when (step) {
            0 -> return S.t198
            1 -> return S.t199
            2 -> return S.t200
            3 -> return S.t201
            4 -> return S.t202
            5 -> return S.t203
            6 -> return S.t204
            7 -> return S.t205
            8 -> return S.t206
            9 -> return S.t207
            10 -> return S.t208
            11 -> return S.t209
            12 -> return S.t210
            13 -> return S.t211
            14 -> return S.t212
            15 -> return S.t213
            16 -> return S.t214
            17 -> return S.t215
            18 -> return S.t216
            19 -> return S.t217
            20 -> return S.t218
            21 -> return S.t219
            22 -> return S.t220
            23 -> return S.t221
            24 -> return S.t222
            25 -> return "测试喷嘴动作启动"
            26 -> return "测试喷嘴工作结束"
            27 -> return "喷嘴复位启动"
            28 -> return "喷嘴复位结束"
            29 -> return "面碗取货复位"
            else -> return S.t223
        }
    }

    fun errMsg(ec: Int): String {

        if (ec.isSetBit(7)) {
            return HeaterProto.errMsg(ec and 0x7F)
        }

        when (ec) {
            0x00 -> return S.t224
            0x01 -> return S.t225
            0x02 -> return S.t226
            0x03 -> return S.t227
            0x04 -> return S.t228
            0x05 -> return S.t229
            0x06 -> return S.t230
            0x07 -> return S.t231
            0x08 -> return S.t232
            0x09 -> return S.t233
            0x0A -> return S.t234
            0x0B -> return S.t235
            0x0C -> return S.t236
            0x0D -> return S.t237
            0x0E -> return S.t238
            0x0F -> return S.t239
            0x10 -> return S.t240
            0x11 -> return S.t241
            0x12 -> return S.t242
            0x13 -> return S.t243
            0x14 -> return S.t244
            0x15 -> return S.t245
            0x16 -> return S.t246
            0x17 -> return S.t247
            0x18 -> return S.t248
            0x19 -> return S.t249
            0x1A -> return S.t265
            0x1B -> return S.t266
            else -> return S.t250
        }
    }

    private fun parseStatus(frame: Frame) {
        val tmp = MainStatus()
        frame.parse(
            tmp.appVersion,
            tmp.sw2,
            tmp.position,
            tmp.ch11,
            tmp.ch12,
            tmp.rotate,
            tmp.elevator,
            tmp.fetch,
            tmp.heat,
            tmp.pasta,
            tmp.extern,
            tmp.pick
        )
        if (tmp != this.status) {
            NetClient.notify(REQ_MAIN_STATUS, frame.data)
        }
        this.status = tmp
        bus.post(MainStatusEvent())
    }

    private fun parseFridge(frame: Frame) {
        val tmp = FridgeStatus()
        frame.parse(tmp.sw, tmp.temp)
        if (tmp != fridge) {
            NetClient.notify(REQ_FRIDGE_STATUS, frame.data)
        }
        fridge = tmp
        bus.post(FridgeStatusEvent())
    }

    private fun onExcept(frame: Frame) {
        val ec = UInt8()
        val msg = ByteView()
        frame.parse(ec, msg)
        bus.post(MainExceptEvent(ec.value, msg.toString()))
    }

    private fun onBarcode(frame: Frame) {
        val col = UInt8()
        val row = UInt8()
        val err = UInt8()
        val barcode = ByteView()

        frame.parse(col, row, err, barcode)
        bus.post(ScanBarcodeEvent(col.value, row.value, err.value, barcode.toString()))
    }

    private fun onPorg(frame: Frame) {
        val step = UInt8()
        val ec = UInt8()
        frame.parse(step, ec)
        bus.post(CookProgEvent(progMsg(step.value, ec.value)))
    }

    fun onRecv(frame: Frame) {
        val req = frame.request()

        when (req) {
            Except -> onExcept(frame)
            StatusUpload -> parseStatus(frame)
            FridgeStatusUpload -> parseFridge(frame)
            Scan -> onBarcode(frame)
            PickupCooking -> onPorg(frame)
        }
    }
}
